 /*
 * 文件名：GenericDAO.java
 * 版权：Copyright by www.wootide.com
 * 描述：
 * 修改人：qianfm
 * 修改时间：Sep 11, 2012
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */
package com.wootide.cms.manager.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.wootide.cms.common.manager.QueryCondition;
import com.wootide.cms.common.manager.SHException;


/**
 * 〈一句话功能简述〉 〈功能详细描述〉
 * 
 * @author qianfm
 * @version Sep 11, 2012
 * @see GenericDAO
 * @since
 */

public class GenericDAO<T, ID extends Serializable> extends HibernateDaoSupport
        implements IGenericDAO<T, Serializable> {

    // private static final Logger LOGGER = Logger.getLogger(GenericDAO.class);

    protected Class<T> entityClass;

    public GenericDAO() {

    }

    @SuppressWarnings("unchecked")
    protected Class getEntityClass() {
        if (entityClass == null) {
            entityClass = (Class<T>) ((ParameterizedType) getClass()
                    .getGenericSuperclass()).getActualTypeArguments()[0];
            logger.debug("T class = " + entityClass.getName());
        }
        return entityClass;
    }

    public void saveOrUpdate(T t) throws DataAccessException {
        this.getHibernateTemplate().saveOrUpdate(t);
    }

    public boolean contains(T t) throws DataAccessException {
        return getHibernateTemplate().contains(t);
    }

    public void delete(T t, LockMode lockMode) throws DataAccessException {
        getHibernateTemplate().delete(t, lockMode);
    }

    public void delete(T t) throws DataAccessException {
        getHibernateTemplate().delete(t);
    }

    public void deleteAll(Collection<T> entities) throws DataAccessException {
        getHibernateTemplate().deleteAll(entities);
    }

    @SuppressWarnings("unchecked")
    public List<T> find(String queryString, Object value)
            throws DataAccessException {
        List<T> find = (List<T>) getHibernateTemplate()
                .find(queryString, value);
        return find;
    }

    @SuppressWarnings("unchecked")
    public List<T> find(String queryString, Object[] values)
            throws DataAccessException {
        List<T> find = (List<T>) getHibernateTemplate().find(queryString,
                values);
        return find;
    }

    @SuppressWarnings("unchecked")
    public List<T> find(String queryString) throws DataAccessException {
        return (List<T>) getHibernateTemplate().find(queryString);
    }

    public void refresh(T t, LockMode lockMode) throws DataAccessException {
        getHibernateTemplate().refresh(t, lockMode);
    }

    public void refresh(T t) throws DataAccessException {
        getHibernateTemplate().refresh(t);
    }

    public Serializable save(T t) throws DataAccessException {
        return getHibernateTemplate().save(t);
    }

    public void saveOrUpdateAll(Collection<T> entities)
            throws DataAccessException {
        getHibernateTemplate().saveOrUpdateAll(entities);
    }

    public void update(T t, LockMode lockMode) throws DataAccessException {
        getHibernateTemplate().update(t, lockMode);
    }

    public void update(T t) throws DataAccessException {
        getHibernateTemplate().update(t);
    }

    @SuppressWarnings("unchecked")
    public List<T> list() throws DataAccessException {
        return getHibernateTemplate().loadAll(getEntityClass());

    }

    @SuppressWarnings("unchecked")
    public List<T> findByNamedQuery(String queryName)
            throws DataAccessException {
        return getHibernateTemplate().findByNamedQuery(queryName);
    }

    @SuppressWarnings("unchecked")
    public List<T> findByNamedQuery(String queryName, Object value)
            throws DataAccessException {
        return getHibernateTemplate().findByNamedQuery(queryName, value);
    }

    @SuppressWarnings("unchecked")
    public List<T> findByNamedQuery(String queryName, Object[] values)
            throws DataAccessException {
        return getHibernateTemplate().findByNamedQuery(queryName, values);
    }

    @SuppressWarnings("unchecked")
    @Override
    public T get(Serializable id) throws DataAccessException {
        T load = (T) getHibernateTemplate().get(getEntityClass(), id);
        return load;
    }

    @SuppressWarnings("unchecked")
    @Override
    public T load(Serializable id) throws DataAccessException {
        T load = (T) getHibernateTemplate().load(getEntityClass(), id);
        return load;
    }

    /**
     * 根据传入的参数构造hql语句进行属性查询，返回单个结果
     * 
     * @param pojoClass
     *            pojoClass
     * @param paramMap
     *            参数集合
     * @return Object Object
     * @throws DAOException
     *             DAOException
     */
    @SuppressWarnings("unchecked")
    protected Object findPojoByAttr(final Class pojoClass,
            final Map<String, Object> paramMap) throws SHException {
        List list = (List) this.getHibernateTemplate().execute(
                new FindPojoByAttrCallBack(pojoClass, paramMap));
        // 如果size=0返回null，否则返回第一个元素

        return list.isEmpty() ? null : list.get(0);
    }

    /**
     * 根据POJO属性查询回调类
     * 
     * @author Administrator
     * @version [1.0, 2010-1-21]
     * @see [相关类/方法]
     * @since [V100R001]
     */
    @SuppressWarnings("unchecked")
    class FindPojoByAttrCallBack implements HibernateCallback {
        private Class pojoClass;

        private Map<String, Object> paramMap;

        public FindPojoByAttrCallBack(Class clz, Map<String, Object> pMap) {
            this.pojoClass = clz;
            this.paramMap = pMap;
        }

        public Object doInHibernate(Session session) throws SQLException {
            // 用于组装hql的StringBuffer
            StringBuffer sbHql = new StringBuffer();

            // 组装hql
            sbHql.append(QueryCondition.HQL_FROM).append(
                    ClassUtils.getShortClassName(pojoClass));
            sbHql.append(QueryCondition.HQL_BLANK).append(
                    QueryCondition.HQL_ALIAS_NAME_A).append(
                    QueryCondition.HQL_WHERE);

            // 获取传入的key
            Set<String> keySet = paramMap.keySet();

            for (String key : keySet) {
                sbHql.append(QueryCondition.HQL_WHERE_AND).append(
                        QueryCondition.HQL_ALIAS_NAME_A).append(
                        QueryCondition.HQL_POINT).append(key);
                String bindName = key;
                if (bindName.indexOf(".") != -1) {
                    bindName = bindName.substring(bindName.indexOf(".") + 1);
                }
                sbHql.append(QueryCondition.HQL_EQUAL
                        + QueryCondition.HQL_COLON + bindName);

            }
            Query query = session.createQuery(sbHql.toString());

            // 设置绑定参数的值

            for (String key : keySet) {
                String bindName = key;
                if (bindName.indexOf(".") != -1) {
                    bindName = bindName.substring(bindName.indexOf(".") + 1);
                }
                query.setParameter(bindName, paramMap.get(key));
            }

            // 获取查询结果
            return query.list();
        }

    }

    /**
     * 根据传入的参数构造hql语句进行属性查询，返回单个结果
     * 
     * @param pojoClass
     *            pojoClass
     * @param paramMap
     *            参数集合
     * @return List 集合
     * @throws DAOException
     *             DAOException
     */
    @SuppressWarnings("unchecked")
    protected List listPojoByAttr(final Class pojoClass,
            final Map<String, Object> paramMap) throws SHException {

        List list = null;
        try {
            list = (List) this.getHibernateTemplate().execute(
                    new ListPojoByAtrrCallBack(pojoClass, paramMap));
        } catch (DataAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return list;
    }

    /**
     * 根据传入的参数构造hql语句进行属性查询，返回单个结果
     * 
     * @param pojoClass
     *            pojoClass
     * @param paramMap
     *            参数集合
     * @return List 集合
     * @throws DAOException
     *             DAOException
     */
    @SuppressWarnings("unchecked")
    protected List fuzzyListPojoByAttr(final Class pojoClass,
            Map<String, Object> paramMap, Map<String, String> orderMap,
            int page, int pageSize) throws SHException {

        List list = (List) this.getHibernateTemplate().execute(
                new FuzzyListPojoByAtrrCallBack(pojoClass, paramMap, orderMap,
                        page, pageSize));

        return list;
    }
	
	/**
     * 根据传入的参数构造hql语句进行属性查询，返回单个结果
     * 
     * @param pojoClass
     *            pojoClass
     * @param paramMap
     *            参数集合
     * @return List 集合
     * @throws DAOException
     *             DAOException
     */
    @SuppressWarnings("unchecked")
    protected int fuzzyListPojoCount(final Class pojoClass,
            Map<String, Object> paramMap
            ) throws SHException {

        List list = (List) this.getHibernateTemplate().execute(
                new FuzzyListPojoCountCallBack(pojoClass, paramMap));

        return list.size();
    }
    
    /**
     * 根据POJO属性模糊查询List回调内部类
     * 
     * 
     * @author Administrator
     * @version [1.0, 2010-1-21]
     * @see [相关类/方法]
     * @since [V100R001]
     */
    @SuppressWarnings("unchecked")
    class FuzzyListPojoCountCallBack implements HibernateCallback {

        private Class pojoClass;

        private Map<String, Object> paramMap;

        public FuzzyListPojoCountCallBack(Class clz, Map<String, Object> pMap) {
            this.pojoClass = clz;
            this.paramMap = pMap;
        }

        public Object doInHibernate(Session session) throws SQLException {
            // 用于组装hql的StringBuffer
            StringBuffer sbHql = new StringBuffer();

            // 组装hql
            sbHql.append(QueryCondition.HQL_FROM).append(
                    ClassUtils.getShortClassName(pojoClass));
            sbHql.append(QueryCondition.HQL_BLANK).append(
                    QueryCondition.HQL_ALIAS_NAME_A).append(
                    QueryCondition.HQL_WHERE);

            // 获取传入的key
            Set<String> keySet = ((LinkedHashMap<String, Object>) paramMap)
                    .keySet();

            for (String key : keySet) {
                sbHql.append(QueryCondition.HQL_WHERE_AND).append(
                        QueryCondition.HQL_ALIAS_NAME_A).append(
                        QueryCondition.HQL_POINT).append(key);
                String bindName = key;
                if (bindName.indexOf(".") != -1) {
                    bindName = bindName.substring(bindName.indexOf(".") + 1);
                }

                sbHql.append(QueryCondition.HQL_LIKE + QueryCondition.HQL_COLON
                        + bindName);

            }
            

            Query query = session.createQuery(sbHql.toString());
            
            // 设置绑定参数的值

            for (String key : keySet) {
                String bindName = key;
                if (bindName.indexOf(".") != -1) {
                    bindName = bindName.substring(bindName.indexOf(".") + 1);
                }
                query.setParameter(bindName, QueryCondition.HQL_LIKE_ANY
                        + paramMap.get(key) + QueryCondition.HQL_LIKE_ANY);
            }

            // 获取查询结果
            return query.list();
        }

    }

	/**
	 * 根据POJO属性查询List回调内部类
	 * 
	 * 
	 * @author Administrator
	 * @version [1.0, 2010-1-21]
	 * @see [相关类/方法]
	 * @since [V100R001]
	 */
	@SuppressWarnings("unchecked")
	class ListPojoByAtrrCallBack implements HibernateCallback {

        private Class pojoClass;

        private Map<String, Object> paramMap;

        public ListPojoByAtrrCallBack(Class clz, Map<String, Object> pMap) {
            this.pojoClass = clz;
            this.paramMap = pMap;
        }

        public Object doInHibernate(Session session) throws SQLException {
            // 用于组装hql的StringBuffer
            StringBuffer sbHql = new StringBuffer();

            // 组装hql
            sbHql.append(QueryCondition.HQL_FROM).append(
                    ClassUtils.getShortClassName(pojoClass));
            sbHql.append(QueryCondition.HQL_BLANK).append(
                    QueryCondition.HQL_ALIAS_NAME_A).append(
                    QueryCondition.HQL_WHERE);

            // 获取传入的key
            Set<String> keySet = paramMap.keySet();

            for (String key : keySet) {
                sbHql.append(QueryCondition.HQL_WHERE_AND).append(
                        QueryCondition.HQL_ALIAS_NAME_A).append(
                        QueryCondition.HQL_POINT).append(key);
                String bindName = key;
                if (bindName.indexOf(".") != -1) {
                    bindName = bindName.substring(bindName.indexOf(".") + 1);
                }
                sbHql.append(QueryCondition.HQL_EQUAL
                        + QueryCondition.HQL_COLON + bindName);

            }

            Query query = session.createQuery(sbHql.toString());

            // 设置绑定参数的值

            for (String key : keySet) {
                String bindName = key;
                if (bindName.indexOf(".") != -1) {
                    bindName = bindName.substring(bindName.indexOf(".") + 1);
                }
                query.setParameter(bindName, paramMap.get(key));
            }

            // 获取查询结果
            return query.list();
        }

    }

    /**
     * 根据POJO属性模糊查询List回调内部类
     * 
     * 
     * @author Administrator
     * @version [1.0, 2010-1-21]
     * @see [相关类/方法]
     * @since [V100R001]
     */
    @SuppressWarnings("unchecked")
    class FuzzyListPojoByAtrrCallBack implements HibernateCallback {

        private Class pojoClass;

        private Map<String, Object> paramMap;

        private Map<String, String> orderMap;

        private int page;

        private int pageSize;

        public FuzzyListPojoByAtrrCallBack(Class clz, Map<String, Object> pMap,
                Map<String, String> oMap, int start, int size) {
            this.pojoClass = clz;
            this.paramMap = pMap;
            this.orderMap = oMap;
            this.page = start;
            this.pageSize = size;
        }

        public Object doInHibernate(Session session) throws SQLException {
            // 用于组装hql的StringBuffer
            StringBuffer sbHql = new StringBuffer();

            // 组装hql
            sbHql.append(QueryCondition.HQL_FROM).append(
                    ClassUtils.getShortClassName(pojoClass));
            sbHql.append(QueryCondition.HQL_BLANK).append(
                    QueryCondition.HQL_ALIAS_NAME_A).append(
                    QueryCondition.HQL_WHERE);

            // 获取传入的key
            Set<String> keySet = ((LinkedHashMap<String, Object>) paramMap)
                    .keySet();

            for (String key : keySet) {
                sbHql.append(QueryCondition.HQL_WHERE_AND).append(
                        QueryCondition.HQL_ALIAS_NAME_A).append(
                        QueryCondition.HQL_POINT).append(key);
                String bindName = key;
                if (bindName.indexOf(".") != -1) {
                    bindName = bindName.substring(bindName.indexOf(".") + 1);
                }

                sbHql.append(QueryCondition.HQL_LIKE + QueryCondition.HQL_COLON
                        + bindName);

            }
            
             StringBuffer sortBuff = new StringBuffer();

            // 排序语句
            Set<String> sortKeySet = orderMap.keySet();
            for (String sortKey : sortKeySet) {
                
                if (sortBuff.indexOf(QueryCondition.HQL_WHERE_ORDERBY) == -1)
                {
                    sortBuff.append(QueryCondition.HQL_WHERE_ORDERBY);
                }

                String sortValue = orderMap.get(sortKey);

                sortBuff.append(QueryCondition.HQL_ALIAS_NAME_A).append(
                        QueryCondition.HQL_POINT).append(sortKey).append(
                        QueryCondition.HQL_BLANK).append(sortValue);
                sortBuff.append(QueryCondition.HQL_COMMA).append(
                        QueryCondition.HQL_BLANK);
            }
            
             // 判断sql结束字符是否正确
            String sortStr = sortBuff.toString();
            String endChar = QueryCondition.HQL_COMMA + QueryCondition.HQL_BLANK;
            if (StringUtils.endsWith(sortStr, endChar))
            {
                sortStr = sortStr.substring(0, sortStr.lastIndexOf(QueryCondition.HQL_COMMA));
            }
            
            // 合并成完整的SQL
            String hqlStr = sbHql.toString() + sortStr;

            Query query = session.createQuery(hqlStr);
            
            query.setFirstResult(page);
            query.setMaxResults(pageSize);

            // 设置绑定参数的值

            for (String key : keySet) {
                String bindName = key;
                if (bindName.indexOf(".") != -1) {
                    bindName = bindName.substring(bindName.indexOf(".") + 1);
                }
                query.setParameter(bindName, QueryCondition.HQL_LIKE_ANY
                        + paramMap.get(key) + QueryCondition.HQL_LIKE_ANY);
            }

            // 获取查询结果
            return query.list();
        }

    }
}
